/* $Header: hostutil.h,v 2.2 01/10/02 10:30:24 przybyls Exp $ */


/***********************************************************************/
/* INCLUDE FILE NAME: hostutil.h                                        */
/* ==================                                                  */
/*                                                                     */
/* Author:  Bob Cook                                                   */
/*                                                                     */
/* COMMENT:                                                            */
/*          Include file for the command processor                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

#ifndef HOST_UTIL_H
#define HOST_UTIL_H

/*****************************/
/*   IFDEFS                  */
/*****************************/


/*****************************/
/*   SYMBOLIC CONSTANTS      */
/*****************************/

/* define the number of internal communication ports */
#define  NUM_PORTS     5

#define   DRTA_PORT       0         /* used for array index - do not change */
#define   DRTB_PORT       DRTA_PORT +1
#define   DRTC_PORT       DRTA_PORT +2  /* Injector 1 */
#define   DRTD_PORT       DRTA_PORT +3  /* Injector 2 */
#define   DRTE_PORT       DRTA_PORT +4  /* Tray       */
#define   INTERNAL_BUFFER 5



/*****************************/
/*   MACROS                  */
/*****************************/



#define ISPRINTABLE(X) (X >0x20 && X < 0x7F) /* true if printable char (!-~) */
#define STRIP(X)  (X == ' ' || X == '\t') /* true if white space (sp or tab) */
#define ISALPHA(X) (X>0x40 && X<0x5B || X>0x60 && X<0x7B) /* alpha (a-z A-Z) */
#define ISALS(X) (X==0x27 && ((p_cmd->comm_port==DRTC_PORT) || (p_cmd->comm_port==DRTD_PORT) || (p_cmd->comm_port==DRTE_PORT) )) /* allow ' for als */
#define ISDIGIT(X) (X >  0x2F && X < 0x3A)      /* true if digit (0-9) */
#define IS_HEX_DIGIT(x) ((x >= 0x30 && x <= 0x39) || (x >= 0x61 && x <= 0x66))
#define IS_UPPER(x) ( ( x >= 'A' ) && ( x <= 'Z' ) )
#define SEPARATOR(X) (X == ',')      /* separator between parameters */

/* make an integer out of two characters for a switch statement */
#define MAKEINT(c1,c2)  ((((INT16)(c2))<<8) | ((INT16)(c1)))

/* used to get the address of a parameter from the cmd structor */
#define GetCmdParm(parm)   &p_cmd->parms[p_cmd->parmv[parm]]

/*==========================================================================*
 * MACRO: Copy2                                                             *
 *                                                                          *
 * PURPOSE: copy 2 characters starting at location "from" to location "to". *
 *          Note, pointers do not get modified.                             *
 * WARNING:                                                                 *
 *==========================================================================*/
/* void Copy2(BIT8 *from,BIT8 *to) */
#define Copy2(from,to)                                                      \
{                                                                           \
   *(to) = *(from);                                                         \
   *((to)+1) = *((from)+1);                                                 \
}                                                                           \



/*==========================================================================*
 * MACRO: GetCmd                                                            *
 *                                                                          *
 * PURPOSE: remove cmd buffer from the head of a singly linked list called  *
 *          "queue" and sets the pointer "p_cmd" pointing to the buffer.    *
 * WARNING:                                                                 *
 *==========================================================================*/
/* GetCmd(CMD_TYPE *p_cmd,CMD_QUEUE_TYPE  queue) */

#define GetCmd(p_cmd, queue)                                                \
{                                                                           \
   INTERRUPTS_OFF;                                                          \
   if((queue).num_entries == 0)                                             \
   {                                                                        \
      /* indicate no more entries available */                              \
      (p_cmd) = (CMD_TYPE *) NULL;                                          \
   }                                                                        \
   else                                                                     \
   {                                                                        \
      /* remove entry from queue and update count */                        \
      (p_cmd) = (queue).head;                                               \
      (queue).head = (p_cmd)->next;                                         \
      (queue).num_entries--;                                                \
   }                                                                        \
   INTERRUPTS_ON;                                                           \
}                                                                           \


/*==========================================================================*
 * MACRO: GetCmdSafe                                                        *
 *                                                                          *
 * PURPOSE: remove cmd buffer from the head of a singly linked list called  *
 *          "queue" and sets the pointer "p_cmd" pointing to the buffer.    *
 * WARNING: ONLY TO BE USED WITH INTERRUPTS OFF AFTER CHECK FOR num-entries *
 *          NOT ZERO!  SEE GetCmd above.                                    *
 *==========================================================================*/
/* GetCmdSafe(CMD_TYPE *p_cmd,CMD_QUEUE_TYPE  queue) */

#define GetCmdSafe(p_cmd, queue)                                         \
{                                                                        \
   /* remove entry from queue and update count */                        \
   (p_cmd) = (queue).head;                                               \
   (queue).head = (p_cmd)->next;                                         \
   (queue).num_entries--;                                                \
}                                                                        \



/*==========================================================================*
 * MACRO: AppendCmd                                                         *
 *                                                                          *
 * PURPOSE: appends indicated buffer "p_cmd" to the end of the specified    *
 *           singly linked list called "queue".                             *
 * WARNING:                                                                 *
 *==========================================================================*/

/* AppendCmd(CMD_TYPE *p_cmd,CMD_QUEUE_TYPE  queue) */

#define AppendCmd(p_cmd, queue)                                             \
{                                                                           \
   if (p_cmd != NULL)                                                       \
   {                                                                         \
      INTERRUPTS_OFF;                                                          \
      (p_cmd)->next = (CMD_TYPE *)NULL;                                        \
      if ( (queue).num_entries == 0 )                                          \
      {                                                                        \
         /* set the head and tail pointers to the new entry */                 \
         (queue).head = (queue).tail = (p_cmd);                                \
      }                                                                        \
      else                                                                     \
      {                                                                        \
         /* set current tail's pointer to the new entry */                     \
         (queue).tail -> next = (p_cmd);                                       \
         (queue).tail = (p_cmd);                                               \
      }                                                                        \
      (queue).num_entries++;                                                   \
      INTERRUPTS_ON;                                                           \
   }                                                                          \
}                                                                           \



/*==========================================================================*
 * MACRO: NextCmd_Port                                                      *
 *                                                                          *
 * PURPOSE: determine the communication port that the next command on the   *
 *           cmd queue originated.                                          *
 * WARNING:                                                                 *
 *==========================================================================*/
/* NextCmd_Port(CMD_QUEUE_TYPE  queue) */
#define NextCmd_Port(queue)     (queue).head->comm_port

/*==========================================================================*
 * MACRO: NextCmd_Dsap                                                      *
 *                                                                          *
 * PURPOSE: determine the dsap for the the next command on the              *
 *           cmd queue.                                                     *
 *             char = 0 for first charactor                                 *
 *             char = 1 for second charactor                                *
 * WARNING:                                                                 *
 *==========================================================================*/
/* NextCmd_Dsap(CMD_QUEUE_TYPE  queue, U_INT16 char) */
#define NextCmd_Dsap(queue,char)     (queue).head->dsap.char_dsap[char]

/*==========================================================================*
 * MACRO: NextCmd_Ssap                                                      *
 *                                                                          *
 * PURPOSE: determine the ssap for the the next command on the              *
 *           cmd queue.                                                     *
 *             char = 0 for first charactor                                 *
 *             char = 1 for second charactor                                *
 * WARNING:                                                                 *
 *==========================================================================*/
/* NextCmd_Ssap(CMD_QUEUE_TYPE  queue, U_INT16 char) */
#define NextCmd_Ssap(queue,char)     (queue).head->ssap.char_ssap[char]


/*****************************/
/*   TYPEDEFS                */
/*****************************/

typedef struct
{
   BIT8 dsap[2];
   BIT8 ssap[2];
   BIT8 opcode[2];
   BIT8 separator1[2];
   BIT8 param[2];
   BIT8 separator2[2];
   BIT8 error[3];
   BIT8 terminator;
} HOST_ERR_RECORD_TYPE;


typedef  struct
{
   BIT8       *pin_msg;      /* pointer to next byte in msg for scanner */
   U_INT16     in_msg_len;   /* length of remaining message */
   U_INT16     chan;         /* comm channel, 0 thru 3 */
} IN_MSG_CB_TYPE;

typedef  struct
{
   BIT8       *p_buffer;      /* pointer to next byte in internal buffer */
   U_INT16     length;        /* current length of buffer in use */
} INTERNAL_BUFFER_TYPE;




/*****************************/
/*   EXTERN                  */
/*****************************/

extern IN_MSG_CB_TYPE  Cmd_Proc_CB; /* variables used in CmdProc for Scan */
extern IN_MSG_CB_TYPE  Wkfile_CB;   /* variables used in Wkfile for Scan */
extern INTERNAL_BUFFER_TYPE  Internal_Buffer; /* loc and len of INTERNAL BUF */
extern U_INT16         Cmd_Port;

extern U_INT16  Host_Error_Count[5];
extern HOST_ERR_RECORD_TYPE Host_Err_Log[5][20];


/*****************************/
/*   FUNCTION PROTOTYPES     */
/*****************************/


INT16 StrLen(BIT8 *str);
void  StrCat(BIT8 *str1,BIT8 *str2);
INT16 StrNCmp(BIT8 *str1,BIT8 *str2,INT16 n);
void StrNCpy(BIT8 *to_str,BIT8 *from_str,INT16 n);
U_INT16 IntToDec(INT32 dec,BIT8 *str);
U_INT16 IntToDecFilled( INT32 dec, BIT8 *str, INT16 size );
U_INT16 IntToDec48(NUM_TYPE num,BIT8 *str);
UI_ERR  HexToInt( BIT8 *str, U_INT32 *value );
UI_ERR  DecToInt(BIT8 *str, U_INT16 signif_dig, INT32 *value);
UI_ERR GetAWordParam( CMD_TYPE *p_cmd, U_INT16 num, U_INT16 *value );

MIO_HDR_TYPE  *GetRespBuf(void);
MIO_HDR_TYPE  *GetMioRespBuf(void);
BIT8 *SetUpRespHdr(MIO_HDR_TYPE  *p_resp_packet,BIT8 *ssap,BIT8 *dsap,BIT8 *opcode);
void SendRespBuf(MIO_HDR_TYPE  *p_resp_packet,U_INT16 parm_len);
void ReturnRespBuf(MIO_HDR_TYPE  *p_resp_packet);
U_INT16 PutIntParam(INT32 value, BIT8   *p_resp_parm, U_INT16 signif_dig);
U_INT16 PutHexParam(U_INT32 value, BIT8  *p_resp_parm);
U_INT16 PutAsciiParam(BIT8  *from_loc, BIT8   *to_loc);
void CmdErrorHandler(CMD_TYPE *p_cmd,U_INT16 param,UI_ERR error);
INT16 DoCmd(CMD_TYPE *p_cmd, BIT8 *p_resp_parm, const METHCMD  *p_cmd_table);
INT16 DoCmdWithResponse(CMD_TYPE *p_cmd, BIT8 *p_resp_parm, const METHCMD  *p_cmd_table);
INT16 DoStatus(CMD_TYPE *p_cmd,BIT8 *p_resp_parm,const METHCMD *p_cmd_table);

CMD_TYPE *GetMsg(BIT8  **p_get_buf);
CMD_TYPE *GetQ2Msg(BIT8  **p_get_buf);
CMD_TYPE *GetQ3Msg(BIT8  **p_get_buf);
void ReturnGetBuf(CMD_TYPE *p_cmd_hdr);
MIO_HDR_TYPE  *AcquirePutBuf(BIT8 **p_put_buf);
void PutMsg(MIO_HDR_TYPE  *p_mio_hdr,U_INT16  port,U_INT16  length);
MIO_HDR_TYPE  *AcquireMIOPutBuf(BIT8 **p_put_buf);
void PutMIOMsg(MIO_HDR_TYPE  *p_mio_hdr,U_INT16  length);
void ExecCmds( CMD_QUEUE_TYPE *Cmd_Q,
         INT16 (*XXOpcodes)(CMD_TYPE *p_cmd,BIT8 *p_resp_parm,U_INT16 max_resp_len) );
void ExecWkfileCmds( CMD_TYPE *p_cmd,
         INT16 (*XXOpcodes)(CMD_TYPE *p_cmd,BIT8 *p_resp_parm,U_INT16 max_resp_len) );

U_INT16  CmdsRemaining(void);
U_INT16  ProcessCmds(void);
INT16  PathTableEntry(BIT8  *sap);
void CleanUpMsg(IN_MSG_CB_TYPE  *msg);

#  pragma SECTION PROG=rom3
UI_ERR Scan(IN_MSG_CB_TYPE *msg,CMD_TYPE  *p_cmd);
#  pragma SECTION UNDO


INT16 AddTowerSetpts (POSITION p, BIT8 *string);
UI_ERR SetTowerSetpoints (POSITION p, CMD_TYPE *p_cmd, BIT8 check_only, INT8 index);
INT16 AddTraySetpts (BIT8 *string);
UI_ERR SetTraySetpoints (CMD_TYPE *p_cmd, BIT8 check_only, INT8 index);



#endif
